package dk.au.cs.peterbn.spoonprocessing;

import spoon.processing.Processor;
import spoon.processing.Severity;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtExecutable;
import spoon.reflect.declaration.CtSimpleType;
import spoon.support.StandardEnvironment;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: peter
 * Date: 10/12/11
 * Time: 11:18 AM
 * To change this template use File | Settings | File Templates.
 */
public class CollectingEnvironment extends StandardEnvironment {

    private int errors;
    private int warnings;
    private List<ReportItem> reportItems = new ArrayList<ReportItem>();


    public int getErrors() {
        return errors;
    }

    public int getWarnings() {
        return warnings;
    }

    public List<ReportItem> getReportItems() {
        return reportItems;
    }

    @Override
    public void report(Processor<?> processor, Severity severity, CtElement element, String message) {
        StringBuffer buffer = new StringBuffer();

        this.prefix(buffer, severity);

        // Adding message
        buffer.append(message);

        // Add sourceposition (javac format)
        CtSimpleType<?> type = (element instanceof CtSimpleType) ? (CtSimpleType<?>) element
                : element.getParent(CtSimpleType.class);
        SourcePosition sp = element.getPosition();

        if (sp == null) {
            buffer.append(" (Unknown Source)");
        } else {
            buffer.append(" at " + type.getQualifiedName() + ".");
            CtExecutable<?> exe = (element instanceof CtExecutable) ? (CtExecutable<?>) element
                    : element.getParent(CtExecutable.class);
            if (exe != null) {
                buffer.append(exe.getSimpleName());
            }
            buffer.append("(" + sp.getFile().getName() + ":" + sp.getLine()
                    + ")");
        }

        this.print(buffer, severity);
    }

    @Override
    public void report(Processor<?> processor, Severity severity, String message) {
        StringBuffer buffer = new StringBuffer();

        this.prefix(buffer, severity);
        // Adding message
        buffer.append(message);
        this.print(buffer, severity);
    }


    private void prefix(StringBuffer buffer, Severity severity) {
        // Prefix message
        switch (severity) {
            case ERROR:
                buffer.append("error: ");
                errors++;
                break;
            case WARNING:
                buffer.append("warning: ");
                warnings++;
                break;
            case MESSAGE:
                break;
        }
    }

    private void print(StringBuffer buffer, Severity severity) {
        switch (severity) {
            case ERROR:
            case WARNING:
                System.out.println(buffer.toString());
                break;
            default:
                if (isVerbose()) {
                    System.out.println(buffer.toString());
                }
        }
        reportItems.add(new ReportItem(buffer.toString(), severity));
    }


    public static class ReportItem {
        public final String msg;
        public final Severity severity;

        public ReportItem(String msg, Severity severity) {
            this.msg = msg;
            this.severity = severity;
        }
    }
}
